package net.ncraft.mc.easyframework.sql;

import com.zaxxer.hikari.HikariDataSource;
import net.ncraft.mc.easyframework.FunctionRegister;
import net.ncraft.mc.easyframework.context.ApplicationContext;
import net.ncraft.mc.easyframework.context.anno.Autowired;
import net.ncraft.mc.easyframework.context.anno.Bean;
import net.ncraft.mc.easyframework.context.anno.Component;
import net.ncraft.mc.easyframework.sql.configuration.SqlConfiguration;
import net.ncraft.mc.easyframework.sql.core.DefaultSqlApplication;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSessionManager;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;

import javax.sql.DataSource;

@Component
public class EasySqlAutoRegister implements FunctionRegister {
    @Autowired
    private ApplicationContext context;
    @Autowired
    private SqlConfiguration sqlConfiguration;
    @Autowired
    private SqlApplication sqlApplication;

    @Override
    public void register() {
        if (sqlConfiguration == null) {
            throw new RuntimeException("请配置数据库!");
        }
        sqlApplication.scan(sqlConfiguration.getApplication());
        sqlApplication.register();
    }

    @Bean(ignoreMethodName = true, order = 4)
    public SqlSessionManager sqlSessionManager(Configuration configuration) {
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configuration);
        return SqlSessionManager.newInstance(factory);
    }

    @Bean(ignoreMethodName = true, order = 1)
    public HikariDataSource hikariDataSource() {
        if (sqlConfiguration == null) {
            throw new RuntimeException("请配置数据库!");
        }
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(sqlConfiguration.getUrl());
        dataSource.setUsername(sqlConfiguration.getUsername());
        dataSource.setPassword(sqlConfiguration.getPassword());
        dataSource.setMaxLifetime(sqlConfiguration.getMaxLifetime());
        return dataSource;
    }

    @Bean(ignoreMethodName = true, order = 1)
    public TransactionFactory transactionFactory() {
        return new ManagedTransactionFactory();
    }

    @Bean(ignoreMethodName = true, order = 2)
    public Environment environment(DataSource dataSource, TransactionFactory transactionFactory) {
        return new Environment("default", transactionFactory, dataSource);
    }

    @Bean(ignoreMethodName = true, order = 3)
    public Configuration configuration(Environment environment) {
        Configuration configuration = new Configuration(environment);
        configuration.setMapUnderscoreToCamelCase(sqlConfiguration.getMapUnderscoreToCamelCase());
        return configuration;
    }

    @Bean(ignoreMethodName = true)
    public SqlApplication daoApplication(Configuration configuration, SqlSessionManager manager) {
        return new DefaultSqlApplication(context, configuration, manager);
    }

}
